﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DeviceNotificationHandler.cs" company="Matthias Friedrich">
//   Copyright © Matthias Friedrich 2009
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace DeviceManagement
{
	using System;
	using System.ComponentModel;
	using System.Windows.Forms;

	public class DeviceNotificationHandler : IDeviceNotificationHandler, IDisposable
	{
		private static readonly object DeviceMessageEvent = new object();

		protected readonly EventHandlerList Events = new EventHandlerList();

		public DeviceNotificationHandler()
		{
		}

		protected void InvokeEvent(object ev, DeviceNotificationEventArgs e)
		{
			var handler = (EventHandler<DeviceNotificationEventArgs>)this.Events[ev];
			if (handler != null)
			{
				handler(this, e);
			}
		}

		protected virtual void OnDeviceMessage(DeviceNotificationEventArgs e)
		{
			this.InvokeEvent(DeviceMessageEvent, e);
		}

		#region DeviceSpecific

		private static readonly object deviceSpecificEvent = new object();

		void IDeviceNotificationHandler.DeviceSpecificEvent(Message m)
		{
			this.OnDeviceSpecificEvent(new DeviceNotificationEventArgs(m));
		}

		private void OnDeviceSpecificEvent(DeviceNotificationEventArgs e)
		{
			this.InvokeEvent(deviceSpecificEvent, e);
		}

		public event EventHandler<DeviceNotificationEventArgs> DeviceSpecific
		{
			add
			{
				this.Events.AddHandler(deviceSpecificEvent, value);
			}

			remove
			{
				this.Events.RemoveHandler(deviceSpecificEvent, value);
			}
		}

		#endregion

		#region DeviceNodesChanged

		private static readonly object deviceNodesChangedEvent = new object();

		void IDeviceNotificationHandler.DeviceNodesChanged(Message m)
		{
			this.OnDeviceNodesChanged(new DeviceNotificationEventArgs(m));
		}

		protected virtual void OnDeviceNodesChanged(DeviceNotificationEventArgs e)
		{
			this.InvokeEvent(deviceNodesChangedEvent, e);
		}

		public event EventHandler<DeviceNotificationEventArgs> DeviceNodesChanged
		{
			add
			{
				this.Events.AddHandler(deviceNodesChangedEvent, value);
			}

			remove
			{
				this.Events.RemoveHandler(deviceNodesChangedEvent, value);
			}
		}

		#endregion

		#region QueryChangeConfiguration

		private static readonly object QueryChangeConfigurationEvent = new object();

		void IDeviceNotificationHandler.QueryChangeConfiguration(Message m)
		{
			this.OnQueryChangeConfiguration(new DeviceNotificationEventArgs(m));
		}

		protected virtual void OnQueryChangeConfiguration(DeviceNotificationEventArgs e)
		{
			this.InvokeEvent(QueryChangeConfigurationEvent, e);
		}

		public event EventHandler<DeviceNotificationEventArgs> QueryChangeConfiguration
		{
			add
			{
				this.Events.AddHandler(QueryChangeConfigurationEvent, value);
			}

			remove
			{
				this.Events.RemoveHandler(QueryChangeConfigurationEvent, value);
			}
		}

		#endregion

		#region ConfigurationChangeCanceled

		private static readonly object ConfigurationChangeCanceledEvent = new object();

		void IDeviceNotificationHandler.ConfigurationChangeCanceled(Message m)
		{
			this.OnConfigurationCanceled(new DeviceNotificationEventArgs(m));
		}

		protected virtual void OnConfigurationCanceled(DeviceNotificationEventArgs e)
		{
			this.InvokeEvent(ConfigurationChangeCanceledEvent, e);
		}

		public event EventHandler<DeviceNotificationEventArgs> ConfigurationChangeCanceled
		{
			add
			{
				this.Events.AddHandler(ConfigurationChangeCanceledEvent, value);
			}

			remove
			{
				this.Events.RemoveHandler(ConfigurationChangeCanceledEvent, value);
			}
		}

		#endregion

		#region DeviceRemovePending

		private static readonly object DeviceRemovePendingEvent = new object();

		void IDeviceNotificationHandler.DeviceRemovePending(Message m)
		{
			this.OnDeviceRemovePending(new DeviceNotificationEventArgs(m));
		}

		protected virtual void OnDeviceRemovePending(DeviceNotificationEventArgs e)
		{
			this.InvokeEvent(DeviceRemovePendingEvent, e);
		}

		public event EventHandler<DeviceNotificationEventArgs> DeviceRemovePending
		{
			add
			{
				this.Events.AddHandler(DeviceRemovePendingEvent, value);
			}

			remove
			{
				this.Events.RemoveHandler(DeviceRemovePendingEvent, value);
			}
		}

		#endregion

		#region DeviceRemoveComplete

		private static readonly object DeviceRemoveCompleteEvent = new object();

		void IDeviceNotificationHandler.DeviceRemoveComplete(Message m)
		{
			var e = new DeviceNotificationEventArgs(m);

			if (e.IsHandle())
			{
				DeviceHandle handle = e.GetHandle();
				bool result = DeviceBroadcast.UnregisterDeviceNotification(handle.NotificationHandle);
			}

			this.OnDeviceRemoveComplete(e);
		}

		protected virtual void OnDeviceRemoveComplete(DeviceNotificationEventArgs e)
		{
			this.InvokeEvent(DeviceRemoveCompleteEvent, e);
		}

		public event EventHandler<DeviceNotificationEventArgs> DeviceRemoveComplete
		{
			add
			{
				this.Events.AddHandler(DeviceRemoveCompleteEvent, value);
			}

			remove
			{
				this.Events.RemoveHandler(DeviceRemoveCompleteEvent, value);
			}
		}

		#endregion

		#region DeviceQueryRemoveFailed

		private static readonly object DeviceQueryRemoveFailedEvent = new object();

		void IDeviceNotificationHandler.DeviceQueryRemoveFailed(Message m)
		{
			this.OnDeviceQueryRemoveFailed(new DeviceNotificationEventArgs(m));
		}

		protected virtual void OnDeviceQueryRemoveFailed(DeviceNotificationEventArgs e)
		{
			this.InvokeEvent(DeviceQueryRemoveFailedEvent, e);
		}

		public event EventHandler<DeviceNotificationEventArgs> DeviceQueryRemoveFailed
		{
			add
			{
				this.Events.AddHandler(DeviceQueryRemoveFailedEvent, value);
			}

			remove
			{
				this.Events.RemoveHandler(DeviceQueryRemoveFailedEvent, value);
			}
		}

		#endregion

		#region DeviceQueryRemove

		private static readonly object DeviceQueryRemoveEvent = new object();

		void IDeviceNotificationHandler.DeviceQueryRemove(Message m)
		{
			var e = new DeviceNotificationCancelEventArgs(m);
			this.OnDeviceQueryRemove(e);

			if (e.Cancel)
			{
				m.Result = new IntPtr(DeviceBroadcast.BROADCAST_QUERY_DENY);
			}
			else
			{
				m.Result = new IntPtr(1);
			}
		}

		protected virtual void OnDeviceQueryRemove(DeviceNotificationEventArgs e)
		{
			this.InvokeEvent(DeviceQueryRemoveEvent, e);
		}

		public event EventHandler<DeviceNotificationEventArgs> DeviceQueryRemove
		{
			add
			{
				this.Events.AddHandler(DeviceQueryRemoveEvent, value);
			}

			remove
			{
				this.Events.RemoveHandler(DeviceQueryRemoveEvent, value);
			}
		}

		#endregion

		#region DeviceArrival

		private static readonly object DeviceArrivalEvent = new object();

		void IDeviceNotificationHandler.DeviceArrival(Message m)
		{
			this.OnDeviceArrival(new DeviceNotificationEventArgs(m));
		}

		protected virtual void OnDeviceArrival(DeviceNotificationEventArgs e)
		{
			this.InvokeEvent(DeviceArrivalEvent, e);
		}

		public event EventHandler<DeviceNotificationEventArgs> DeviceArrival
		{
			add
			{
				this.Events.AddHandler(DeviceArrivalEvent, value);
			}

			remove
			{
				this.Events.RemoveHandler(DeviceArrivalEvent, value);
			}
		}

		#endregion

		#region DeviceConfigurationChanged

		private static readonly object deviceConfigurationChanged = new object();

		void IDeviceNotificationHandler.DeviceConfigurationChanged(Message m)
		{
			this.OnDeviceConfigurationChanged(new DeviceNotificationEventArgs(m));
		}

		protected virtual void OnDeviceConfigurationChanged(DeviceNotificationEventArgs e)
		{
			this.InvokeEvent(DeviceArrivalEvent, e);
		}

		public event EventHandler<DeviceNotificationEventArgs> DeviceConfigurationChanged
		{
			add
			{
				this.Events.AddHandler(deviceConfigurationChanged, value);
			}

			remove
			{
				this.Events.RemoveHandler(deviceConfigurationChanged, value);
			}
		}

		#endregion

		#region IDisposable Members

		void IDisposable.Dispose()
		{
			this.Dispose(true);
		}

		protected bool Disposed { get; private set; }

		protected virtual void Dispose(bool disposing)
		{
			if (disposing && !this.Disposed)
			{
				this.Disposed = true;
			}

			this.Events.Dispose();
		}

		~DeviceNotificationHandler()
		{
			this.Dispose(false);
			GC.SuppressFinalize(this);
		}

		#endregion
	}
}